package cn.javadog.cloud.starter.jsonfilter.converter;

import cn.javadog.cloud.starter.jsonfilter.annotation.JsonFilter;
import cn.javadog.cloud.starter.jsonfilter.domain.JsonFilterObject;
import cn.javadog.cloud.starter.jsonfilter.exception.JsonFilterException;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.Arrays;
import java.util.Objects;

/**
 * @author yuy
 * @date 2020-11-09 15:42
 **/
@ControllerAdvice
public class JsonFilterResponseBodyAdvice implements ResponseBodyAdvice {

    @Override
    public boolean supports(MethodParameter methodParameter, Class converterType) {
        // 必须有指定注解才拦截
        return methodParameter.getMethod().isAnnotationPresent(JsonFilter.class);
    }

    @Override
    public Object beforeBodyWrite(Object data, MethodParameter methodParameter, MediaType mediaType, Class converterType, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        // 值为空，或者 方法上没有 JsonFilter 注解
        if (Objects.isNull(data)) {
            return null;
        }
        /**
         * 处理注解的过滤配置
         * java.lang.reflect.Method.getAnnotation(Class <T> annotationClass)
         * @return: 如果存在于此元素，则返回该元素注释指定的注释类型，否则返回为null
         * 在处理类中，会对应强转为对应的类型，如JsonFilter类
         */
        JsonFilterObject jsonFilterObject = new JsonFilterObject();
        JsonFilter obj = methodParameter.getMethod().getAnnotation(JsonFilter.class);
        handleAnnotation(obj, jsonFilterObject);
        jsonFilterObject.setData(data);
        return jsonFilterObject;
    }

    /**
     * 目前只支持一个 JsonFilter
     * 获取注解使用处的参数信息，如@JsonFilter(clazz = Address.class,fields = {"school", "home", "user"})
     */
    private void handleAnnotation(JsonFilter jsonFilter, JsonFilterObject jsonFilterObject) {
        Class<?> objClass = jsonFilter.target();

        // todo 为啥阿里插件显示一直是true
        if (Objects.isNull(objClass)) {
            throw new JsonFilterException();
        }

        jsonFilterObject.getFields().addAll(Arrays.asList(jsonFilter.fields()));
        jsonFilterObject.setClazz(objClass);
        jsonFilterObject.setExclude(jsonFilter.exclude());
    }

}
